/**
 * @Author: lena
 * @Description:锁操作
 * @Version: 1.0.0
 * @Date: 2021/9/9 20:41
 */

package lib

import (
	"fmt"
	"strconv"
	"sync"
)

// WaitGroup
var wg sync.WaitGroup

func WaitGroup1() {
	wg.Add(3) // +3
	f1 := func() {
		sum := 0
		for i := 0; i < 100; i++ {
			sum += i
		}
		fmt.Println("finish", sum)
		wg.Done() // -1
	}
	go f1()
	go f1()
	go f1()
	wg.Wait() // 阻塞直到=0才退出 会等待所有协程执行完才结束
	fmt.Println("main over")
}

// 互斥锁
var lock sync.Mutex
var x = 0

func Lock1() {
	wg.Add(3)
	go addLock()
	go addLock()
	go addLock()
	wg.Wait()
	fmt.Println(x) // 30000
}
func addLock() {
	defer wg.Done()
	for i := 0; i < 10000; i++ {
		lock.Lock() // 加锁：获取到锁的唯一一个协程才能操作
		x++
		lock.Unlock() // 解锁
	}
}

// 读写锁
var rwLock sync.RWMutex
var y = 0

func Lock2() {
	wg.Add(1100)
	for i := 0; i < 100; i++ {
		go write()
	}
	for i := 0; i < 1000; i++ {
		go read()
	}
}
func read() {
	defer wg.Done()
	rwLock.RLock() // 加读锁
	fmt.Println("read:", y)
	rwLock.RUnlock() // 释放
}
func write() {
	defer wg.Done()
	rwLock.Lock() // 加写锁
	y++
	fmt.Println("write:", y)
	rwLock.Unlock() // 释放
}

// Map1 sync.map并发安全的map
func Map1() {
	var m sync.Map
	var wg1 sync.WaitGroup
	for i := 0; i < 20; i++ {
		wg1.Add(1)
		go func(n int) {
			key := strconv.Itoa(n) // int转string
			m.Store(key, n)        // 存"n":n
			value, _ := m.Load(key)
			fmt.Println(key, value)
			wg1.Done()
		}(i)
	}
	wg1.Wait()
}

// Once1 sync.Once的Do方法：保证只执行一次，单例模式
func Once1(once *sync.Once) {
	// func (o *Once) Do(f func()) ：传入的方法必须无参无返回值
	once.Do(method)
}
func method() {
	fmt.Println("我被调用了！！！")
}
